package ro.fortech.workshop_demo.access.webservice.handlers;

import org.apache.http.HttpResponse;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import ro.fortech.workshop_demo.access.webservice.JSONParser;
import ro.fortech.workshop_demo.access.webservice.WSConstants;
import ro.fortech.workshop_demo.access.webservice.callbacks.GrandPrixParserDelegate;
import ro.fortech.workshop_demo.data.GrandPrix;

import java.io.IOException;
import java.util.ArrayList;

/**
 * \ * User: florinv
 * Date: 4/16/13
 * Time: 12:21 PM
 * \
 */
public class GrandPrixParser extends JSONParser {
    /**
     * Constant for the MRData tag
     */
    private static final String MR_DATA_TAG = "MRData";
    /**
     * Constant for the RaceTable tag
     */
    private static final String RACE_TABLE_TAG = "RaceTable";
    /**
     * Constant for the Races tag
     */
    private static final String RACES_TAG = "Races";
    /**
     * Constant for the Round tag
     */
    private static final String ROUND_TAG = "round";
    /**
     * Constant for the RaceName tag
     */
    private static final String RACE_NAME_TAG = "raceName";
    /**
     * Constant for the Circuit tag
     */
    private static final String CIRCUIT_TAG = "Circuit";
    /**
     * Constant for the CircuitName tag
     */
    private static final String CIRCUIT_NAME_TAG = "circuitName";
    /**
     * Constant for the Url tag
     */
    private static final String URL_TAG = "url";
    /**
     * Constant for the Location tag
     */
    private static final String LOCATION_TAG = "Location";
    /**
     * Constant for the Locality tag
     */
    private static final String LOCALITY_TAG = "locality";
    /**
     * Constant for the Country tag
     */
    private static final String COUNTRY_TAG = "country";
    /**
     * Constant for the date tag
     */
    private static final String DATE_TAG = "date";

    /**
     * Delegate for the response callback
     */
    private GrandPrixParserDelegate delegate;
    /**
     * ArrayList holding the grand prix list from the selected season
     */
    private ArrayList<GrandPrix> grandPrixList;

    /**
     * Constructor
     */
    public GrandPrixParser(GrandPrixParserDelegate delegate) {
        this.delegate = delegate;
        this.grandPrixList = new ArrayList<GrandPrix>();
    }

    @Override
    public String handleResponse(HttpResponse httpResponse) throws IOException {
        responseCode = httpResponse.getStatusLine().getStatusCode();
        if (responseCode == 200) {
            try {
                parse(httpResponse);
            } catch (JSONException e) {
                connectionFailed();
                e.printStackTrace();
            }
        } else {
            delegate.getSeasonsCallback(null, responseCode);
        }
        return null;
    }

    @Override
    protected void parse(HttpResponse httpResponse) throws JSONException, IOException {
        // The HTTP response is a JSON object
        JSONObject baseJSONObject = new JSONObject(read(httpResponse.getEntity().getContent()));
        // MRData is a separate JSON object inside the base object
        if (baseJSONObject.has(MR_DATA_TAG) && !baseJSONObject.isNull(MR_DATA_TAG)) {
            JSONObject mrDataJSONObject = baseJSONObject.getJSONObject(MR_DATA_TAG);
            // RaceTable is a separate JSON object inside the mrDataJSONObject
            if (mrDataJSONObject.has(RACE_TABLE_TAG) && !mrDataJSONObject.isNull(RACE_TABLE_TAG)) {
                JSONObject raceTableJSONObject = mrDataJSONObject.getJSONObject(RACE_TABLE_TAG);
                // Races is a separate JSON array inside the raceTableJSONObject
                if (raceTableJSONObject.has(RACES_TAG) && !raceTableJSONObject.isNull(RACES_TAG)) {
                    JSONArray racesJSONArray = raceTableJSONObject.getJSONArray(RACES_TAG);
                    // Get each race from the racesJSONArray
                    for (int i = 0; i < racesJSONArray.length(); i++) {
                        // Instantiate a GrandPrix dto
                        GrandPrix grandPrix = new GrandPrix();
                        // Get the race JSON object
                        JSONObject raceJSONObject = racesJSONArray.getJSONObject(i);
                        // Get the round
                        if (raceJSONObject.has(ROUND_TAG)) {
                            grandPrix.setRoundNumber(raceJSONObject.getString(ROUND_TAG));
                        }
                        // Get the grand prix name
                        if (raceJSONObject.has(RACE_NAME_TAG)) {
                            grandPrix.setRaceName(raceJSONObject.getString(RACE_NAME_TAG));
                        }
                        // Circuit is a separate JSON object inside the raceJSONObject
                        if (raceJSONObject.has(CIRCUIT_TAG) && !raceJSONObject.isNull(CIRCUIT_TAG)) {
                            JSONObject circuitJSONObject = raceJSONObject.getJSONObject(CIRCUIT_TAG);
                            // Get the circuit name
                            if (circuitJSONObject.has(CIRCUIT_NAME_TAG)) {
                                grandPrix.setCircuitName(circuitJSONObject.getString(CIRCUIT_NAME_TAG));
                            }
                            // Get the circuit details url
                            if (circuitJSONObject.has(URL_TAG)) {
                                grandPrix.setDetailsUrl(circuitJSONObject.getString(URL_TAG));
                            }
                            // Location is a separate JSON object inside the circuitJSONObject
                            if (circuitJSONObject.has(LOCATION_TAG) && !circuitJSONObject.isNull(LOCATION_TAG)) {
                                JSONObject locationJSONObject = circuitJSONObject.getJSONObject(LOCATION_TAG);
                                // Get the locality name
                                if (locationJSONObject.has(LOCALITY_TAG)) {
                                    grandPrix.setLocalityName(locationJSONObject.getString(LOCALITY_TAG));
                                }
                                // Get the country name
                                if (locationJSONObject.has(COUNTRY_TAG)) {
                                    grandPrix.setCountryName(locationJSONObject.getString(COUNTRY_TAG));
                                }
                            }
                        }
                        // Get the date
                        if (raceJSONObject.has(DATE_TAG)) {
                            grandPrix.setDate(raceJSONObject.getString(DATE_TAG));
                        }
                        // Build the country flag url and add it to the dto
                        grandPrix.setCountryFlagUrl(String.format(WSConstants.BASE_COUNTRY_FLAG_URL, grandPrix.getCountryName()));
                        // Add the parsed grand prix dto to the list
                        grandPrixList.add(grandPrix);
                    }
                }
            }
        }
        // Send the result to the manager
        delegate.getSeasonsCallback(grandPrixList, responseCode);
    }

    @Override
    public void connectionFailed() {
        delegate.getSeasonsCallback(null, responseCode);
    }
}
